运行环境
- Xcode 10.1
- Swift 4.2
背景知识
Swift
是一种强类型语言。即默认类型是安全的静态类型。纯Swift类的函数调用已经不再是OC的运行时发送消息,而是类似于C++的vtable,在编译时就确定了调用哪个函数,所以没法通过runtime获取方法,属性。Swift中的动态性可以通过OC运行时来获得,动态性最常用的就是方法替换(Method Swizzling)。
Swift中的动态修饰符
@objc
: 将`Swift 函数 暴露给 OC运行时,但是它仍然不能保证完全动态,编译器会尝试去对它做静态优化@dynamic
: 动态功能修饰符,它能保证函数,属性可以获得动态性
注意:继承自NSObject
的Swift
类,其继承自父类的方法具有动态性,因为是NSObject
中的方法,其他在Swift
中自定义方法,属性需要加@objc
与@dynamic
必须同时加上者两个修饰符获得动态性,否则要报错"'dynamic' instance method 'sayHello' must also be '@objc'"
。若方法的参数,属性类型为Swift
特有的,无法映射到OC的类型上(例如,Character
,Tuple
),不能添加@dynamic
定义一个需要替换方法实现的类(不继承NSObject
)
1 | class SayHello { |
两种方案
- 方案一:用
Swift
中的unsafeBitCast
实现
扩展一个函数 swizzleSayHello()
1 | extension SayHello { |
调用函数
1 | SayHello.swizzleSayHello() |
打印:
1 | Hello Jack,nice to meet you! |
- 方案二:用
method_exchangeImplementations
实现
同样扩展一个函数 swizzleSayHello()
以及实现一个目标函数swizzledSayHello(_ name: String)
1 | extension SayHello { |
调用函数
1 | SayHello.swizzledSayHello() |
打印:
1 | Hello Jack,nice to meet you! |
最后
@convention 关键字可以参考 @convention 以及 @convention